/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.butnet.myframe.servlet;

import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import net.sf.json.JSONException;
import net.sf.json.JSONObject;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

/**
 * 文件上传Servlet
 * @author Administrator
 */
public class UploadProcessServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	/**
     * 上传文件方法
     */
    public final String UPLOAD_FILE = "upload";
    /**
     * 创建上传sessionId
     */
    public final String CREATE_UPLOAD = "createUpload";
    /**
     * 取得上传进度信息
     */
    public final String GET_UPLOAD_INFO = "getUploadInfo";
    /**
     * 停止上传
     */
    public final String STOP_UPLOAD = "stopUpload";
    /**
     * 上传信息所保存的HttpSession名称
     */
    public final String UPLOAD_SESSION_KEY = "uploadSessionKey";
    /**
     * 上传文件保存的根目录
     */
    private File uploadRootFile = null;
    /**
     * 随机对象
     */
    private static Random random = new Random(new Date().getTime());

    @Override
    public void init(ServletConfig config) throws ServletException {
        String uploadRoot = config.getInitParameter("uploadRoot");
        if (uploadRoot == null || uploadRoot.trim().length() == 0) {
            uploadRoot = "uploadRoot";
        }
        String filePath = config.getServletContext().getRealPath("/WEB-INF");
        File file = new File(filePath, uploadRoot);
        if (!file.exists()) {
            file.mkdirs();
        } else {
            if (!file.isDirectory()) {
                for (int i = 0; file.exists(); i++) {
                    uploadRoot = "uploadRoot" + i;
                    file = new File(filePath, uploadRoot);
                }
                file.mkdirs();
            }
        }

        uploadRootFile = file;
        super.init(config);
    }

    /** 
     * Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");
        String method = request.getParameter("method");

        try {
            if (method.equalsIgnoreCase(UPLOAD_FILE)) {
                upload(request, response);
            } else if (method.equalsIgnoreCase(CREATE_UPLOAD)) {
                createUpload(request, response);
            } else if (method.equalsIgnoreCase(GET_UPLOAD_INFO)) {
                getUploadInfo(request, response);
            } else if (method.equalsIgnoreCase(STOP_UPLOAD)) {
                stopUpload(request, response);
            } else {
                JSONObject json = new JSONObject();
                json.put("success", false);
                json.put("msg", "错误的调用方法: " + method);
                response.getWriter().println(json);
            }
        } catch (JSONException e) {
            Logger.getLogger(UploadProcessServlet.class.getName()).log(Level.SEVERE, null, e);
        }
    }

    // <editor-fold defaultstate="collapsed" desc="HttpServlet 方法。单击左侧的 + 号以编辑代码。">
    /** 
     * Handles the HTTP <code>GET</code> method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /** 
     * Handles the HTTP <code>POST</code> method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /** 
     * Returns a short description of the servlet.
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "Short description";
    }// </editor-fold>

    @SuppressWarnings("unchecked")
	private void createUpload(HttpServletRequest request, HttpServletResponse response) throws IOException, JSONException {
        HttpSession session = request.getSession();
        HashMap<String, UploadInfo> uploadSession = (HashMap<String, UploadInfo>) session.getAttribute(UPLOAD_SESSION_KEY);
        if (uploadSession == null) {
            uploadSession = new HashMap<String, UploadInfo>();
            session.setAttribute(UPLOAD_SESSION_KEY, uploadSession);
        }

        String uploadId = request.getParameter("uploadSessionId");
        UploadInfo ui = uploadSession.get(uploadId);
        if (ui != null) {
            JSONObject json = new JSONObject();
            json.put("success", false);
            json.put("msg", "uploadSessionId: " + uploadId + " 已经存在");
            response.getWriter().println(json);
        } else {
            ui = new UploadInfo(uploadId);
            uploadSession.put(uploadId, ui);
            JSONObject json = ui.getJson();
            json.put("success", true);
            json.put("msg", "正在连接");
            response.getWriter().println(json);
        }
    }

    @SuppressWarnings("unchecked")
	private void getUploadInfo(HttpServletRequest request, HttpServletResponse response) throws IOException, JSONException {
        HttpSession session = request.getSession();
        HashMap<String, UploadInfo> uploadSession = (HashMap<String, UploadInfo>) session.getAttribute(UPLOAD_SESSION_KEY);
        if (uploadSession == null) {
            JSONObject json = new JSONObject();
            json.put("success", false);
            json.put("msg", "没有上传数据");
            response.getWriter().println(json);
            return;
        }

        String uploadId = request.getParameter("uploadSessionId");
        UploadInfo ui = uploadSession.get(uploadId);
        if (ui == null) {
            JSONObject json = new JSONObject();
            json.put("success", false);
            response.getWriter().println(json);
        } else {
            if (!ui.getJson().getBoolean("success")) {
                uploadSession.remove(uploadId);
            } else {
                if (ui.getJson().has("progress")) {
                    String progress = ui.getJson().getString("progress");
                    if (progress != null) {
                        if (ui.isRemoveAfterGet()) {
                            uploadSession.remove(uploadId);
                        }
                    }
                } else {
                    ui.getJson().put("progress", "0");
                }
            }
            response.getWriter().println(ui.getJson());
        }
    }

    @SuppressWarnings("unchecked")
	private void stopUpload(HttpServletRequest request, HttpServletResponse response) throws IOException, JSONException {
        HttpSession session = request.getSession();
        HashMap<String, UploadInfo> uploadSession = (HashMap<String, UploadInfo>) session.getAttribute(UPLOAD_SESSION_KEY);
        if (uploadSession == null) {
            JSONObject json = new JSONObject();
            json.put("success", false);
            json.put("msg", "没有上传数据");
            response.getWriter().println(json);
            return;
        }

        String uploadId = request.getParameter("uploadSessionId");
        UploadInfo ui = uploadSession.get(uploadId);
        if (ui == null) {
            JSONObject json = new JSONObject();
            json.put("success", false);
            json.put("msg", "没有上传数据");
            response.getWriter().println(json);
        } else {
            ui.setStop(Boolean.TRUE);
            uploadSession.remove(uploadId);
            JSONObject json = new JSONObject();
            json.put("success", true);
            json.put("msg", "停止上传成功");
            ui.setRemoveAfterGet(true);
            response.getWriter().println(json);
        }
    }

    @SuppressWarnings("unchecked")
	private void upload(HttpServletRequest request, HttpServletResponse response) throws IOException, JSONException {
        HttpSession session = request.getSession();
        HashMap<String, UploadInfo> uploadSession = (HashMap<String, UploadInfo>) session.getAttribute(UPLOAD_SESSION_KEY);
        if (uploadSession == null) {
            uploadSession = new HashMap<String, UploadInfo>();
            session.setAttribute(UPLOAD_SESSION_KEY, uploadSession);
        }

        String uploadId = request.getParameter("uploadSessionId");
        UploadInfo ui = uploadSession.get(uploadId);

        ServletFileUpload sfu = new ServletFileUpload(new DiskFileItemFactory());
        Iterator<FileItem> fii = null;

        final UploadInfo final_ui = ui;

        sfu.setProgressListener(new ProgressListener() {

            public void update(long bytesRead, long contentLength, int items) {
                if (final_ui.getStop() != null && final_ui.getStop().equals(Boolean.TRUE)) {
                    try {
                        final_ui.getJson().remove("progress");
                        final_ui.getJson().put("success", false);
                        final_ui.getJson().put("msg", "上传停止");
                    } catch (JSONException e) {
                        Logger.getLogger(UploadProcessServlet.class.getName()).log(Level.SEVERE, null, e);
                    }
                    return;
                }
                String s = (1.0 * bytesRead / contentLength * 100) + "";
                int i = s.indexOf(".");
                if (i != -1) {
                    String min = s.substring(i + 1);
                    if (min.length() > 2) {
                        min = min.substring(0, 2);
                    }
                    s = s.substring(0, i + 1) + min;
                }
                try {
                    final_ui.getJson().remove("msg");
                    final_ui.getJson().put("success", true);
                    final_ui.getJson().put("progress", s);
                } catch (JSONException ex) {
                    Logger.getLogger(UploadProcessServlet.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        });
        try {
            List<FileItem> list = sfu.parseRequest(request);
            fii = list.iterator();
            File uploadFile = null;
            LinkedHashMap<String, String> properties = new LinkedHashMap<String, String>();// 请求参数
            JSONObject json = new JSONObject();

            while (fii.hasNext()) {
                FileItem stream = fii.next();
                if (!stream.isFormField()) {
                    try {
                        uploadFile = new File(uploadRootFile, new Date().getTime() + "_" + randText(8) + "_" + stream.getName());
                        System.out.println("uploadFile: " + uploadFile);
                        stream.write(uploadFile);
                    } catch (Exception e) {
                        if (uploadFile != null && uploadFile.exists()) {
                            uploadFile.delete();
                        }
                        Logger.getLogger(UploadProcessServlet.class.getName()).log(Level.SEVERE, null, e);
                        json.put("success", false);
                        json.put("msg", "错误请求");
                        response.getWriter().println(json);
                        return;
                    }
                } else {
                    properties.put(stream.getFieldName(), new String(stream.get()));
                }
            }

            final_ui.getJson().put("success", true);
            final_ui.getJson().put("msg", "保存成功");
            final_ui.setRemoveAfterGet(true);
        } catch (FileUploadException ex) {
            Logger.getLogger(UploadProcessServlet.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public static String randText(int length) {
        String re = "";
        int value = 0;
        for (int i = 0; i < length; i++) {
            value = random.nextInt(52);
            if (value < 26) {
                re += ('a' + value);
            } else {
                re += ('A' + (value - 26));
            }
        }
        return re;
    }
}